package com.jyw.custom.huaxi.mos.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSONObject;
import com.jyw.common.constant.CacheConstants;
import com.jyw.common.constant.ConfigKeyConstant;
import com.jyw.common.constant.Constants;
import com.jyw.common.core.domain.model.LoginUser;
import com.jyw.common.core.redis.RedisCache;
import com.jyw.common.exception.ServiceException;
import com.jyw.custom.huaxi.mos.config.HuaxiMosAuthenticationToken;
import com.jyw.custom.huaxi.mos.domain.vo.MosConfig;
import com.jyw.custom.huaxi.mos.service.IHuaxiMosService;
import com.jyw.framework.manager.AsyncManager;
import com.jyw.framework.manager.factory.AsyncFactory;
import com.jyw.framework.web.service.SysLoginService;
import com.jyw.framework.web.service.TokenService;
import com.jyw.system.service.ISysConfigService;
import com.jyw.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class HuaxiMosServiceImpl implements IHuaxiMosService {

    @Resource
    private RedisCache redisCache;

    @Resource
    private ISysConfigService configService;

    @Resource
    private SysLoginService loginService;

    @Resource
    private RestTemplate restTemplate;

    @Autowired
    private TokenService tokenService;

    @Resource
    private AuthenticationManager authenticationManager;

    private MosConfig getMosConfig() {
        String mosConfigStr = configService.selectConfigByKey(ConfigKeyConstant.MOS_CONFIG);
        if (!ObjectUtils.isEmpty(mosConfigStr)) {
            return JSONObject.parseObject(mosConfigStr, MosConfig.class);
        }
        throw new ServiceException("未找到Mos系统配置");
    }

    @Override
    public String getToken() {
        //判断缓存是否存在
        if (redisCache.hasKey(CacheConstants.CUSTOM_HUA_XI_MOS_ACCESS_TOKEN)) {
            return redisCache.getCacheObject(CacheConstants.CUSTOM_HUA_XI_MOS_ACCESS_TOKEN);
        } else {
            /**
             * 获取access_token
             * 获取数据库配置
             * 调用mos接口
             */
            MosConfig mosConfig = getMosConfig();

            ResponseEntity<JSONObject> response = restTemplate.getForEntity(mosConfig.getBaseUrl() + "/gettoken?app_key={app_key}&app_secret={app_secret}"
                    , JSONObject.class,
                    mosConfig.getAppKey(), mosConfig.getAppSecret()
            );
            JSONObject body = response.getBody();
            if (body.getString("code").equals("200")) {
                String accessToken = body.getJSONObject("data").getString("accessToken");
                //写入缓存
                redisCache.setCacheObject(CacheConstants.CUSTOM_HUA_XI_MOS_ACCESS_TOKEN, accessToken, body.getJSONObject("data").getInteger("expiresIn"), TimeUnit.SECONDS);
                return accessToken;
            } else {
                log.error("调用Mos接口,返回结果:{}", body);
                throw new ServiceException("调用Mos接口,获取access_token接口失败");
            }
        }
    }

    @Override
    public String getAuthUser(String code) {
        MosConfig mosConfig = getMosConfig();
        JSONObject body = restTemplate.postForEntity(
                mosConfig.getBaseUrl() + "/sso/getauthuser?access_token={access_token}",
                MapUtil.builder().put("code", code).build(),
                JSONObject.class,
                getToken()
        ).getBody();
        log.info("华西Mos授权码获取用户信息:{}", body);
        if (!body.getString("code").equals("200")) {
            return null;
        }
        return body.getJSONObject("data").getString("employeeId");
    }

    @Override
    public String login(String code) {
        //用户验证
        Authentication authentication = null;
        try {
            //该方法会调用UserDetailServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(new HuaxiMosAuthenticationToken(code));
        } catch (Exception e) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(code, Constants.LOGIN_FAIL, e.getMessage()));
            throw new ServiceException(e.getMessage());
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(code, Constants.LOGIN_SUCCESS, "登录成功"));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        loginService.recordLoginInfo(loginUser.getUserId());
        return tokenService.createToken(loginUser);
    }

    /**
     * 根据用户id获取用户
     *
     * @param userId
     */
    private String getUser(String userId) {
        MosConfig mosConfig = getMosConfig();
        JSONObject body = restTemplate.getForEntity(mosConfig.getBaseUrl() + "/user/get?access_token={access_token}&userId={userId}"
                , JSONObject.class
                , getToken(),userId).getBody();
//        https://open.mobimedical.cn/docs/guide/%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3.html#_2-5-2%E8%AF%BB%E5%8F%96%E6%88%90%E5%91%98
        log.info("华西Mos读取成员:{}", body);
        if (!body.getString("code").equals("200")) {
            return null;
        }
        return body.getJSONObject("data").getString("employeeId");
    }
}
